using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;

namespace ParallelProcessingDemo
{

    public partial class frmMain : Form
    {
        
        delegate void UpdateList(string message, long time);

        SqlConnection AsyncDB;
        public frmMain()
        {
            InitializeComponent();

            AsyncDB = new SqlConnection(txtConnectionString.Text  );

        }

        private void btnFileUpload_Click(object sender, EventArgs e)
        {
            FileUpload(txtFilename.Text);
        }
        
        private void FileUpload(string filename)
        {
            SqlCommand FileUpload = new SqlCommand("FileUpload",AsyncDB );

            FileUpload.CommandType = CommandType.StoredProcedure; 
            FileUpload.Parameters.Add (new SqlParameter ("@filename",SqlDbType.NVarChar ,4000));
            FileUpload.Parameters[0].Value = filename;
            FileUpload.CommandTimeout = 500;

            Cursor currentCursor = this.Cursor;
            this.Cursor = Cursors.WaitCursor;

            Stopwatch sw = new Stopwatch ();
            sw.Start ();
            AsyncDB.Open();
            FileUpload.ExecuteNonQuery();
            AsyncDB.Close();
            sw.Stop ();

            UpdateListStatus(filename, sw.ElapsedMilliseconds);
            this.Cursor = currentCursor;
           
        }

        
        private void txtConnectionString_Validating(object sender, CancelEventArgs e)
        {
            switch (AsyncDB.State )
            {
                case ConnectionState.Closed :
                    break;
                case ConnectionState.Open :
                    AsyncDB.Close(); 
                    break;
                default:
                    e.Cancel = true;
                    break;
                    
            }

            AsyncDB.ConnectionString = txtConnectionString.Text;
            
        }

        private void btnFileUploadAsync_Click(object sender, EventArgs e)
        {
            FileUploadAsync(txtFilename.Text);
        }

        private void FileUploadAsync (string filename)
        {
            SqlCommand FileUpload = new SqlCommand("FileUploadAsync", AsyncDB);
            Guid Handle;
            FileUpload.CommandType = CommandType.StoredProcedure;
            FileUpload.Parameters.Add(new SqlParameter("@filename", SqlDbType.NVarChar, 4000));
            FileUpload.Parameters.Add(new SqlParameter("@handle", SqlDbType.UniqueIdentifier));
            FileUpload.Parameters[0].Value = filename;
            FileUpload.Parameters[1].Direction = ParameterDirection.Output;
            FileUpload.CommandTimeout = 500;

            Cursor currentCursor = this.Cursor;
            this.Cursor = Cursors.WaitCursor;

            Stopwatch sw = new Stopwatch();
            sw.Start();
            AsyncDB.Open();
            FileUpload.ExecuteNonQuery();
            Handle = (Guid)FileUpload.Parameters[1].Value;
            AsyncDB.Close();
            
            sw.Stop();
            BackgroundWorker bwMonitor = new BackgroundWorker();
            bwMonitor.DoWork += new DoWorkEventHandler(bwMonitor_DoWork);
            bwMonitor.RunWorkerAsync(Handle);

            UpdateListStatus(filename , sw.ElapsedMilliseconds);

            this.Cursor = currentCursor;
            

           
        }

        void bwMonitor_DoWork(object sender, DoWorkEventArgs e)
        {

            MonitorQueue((Guid)e.Argument);
        }


        public void MonitorQueue(Guid handle)
        {
            SqlConnection monCon = new SqlConnection();
            monCon.ConnectionString = AsyncDB.ConnectionString;
 
            SqlCommand FileUpload = new SqlCommand("FileUploadMonitor", monCon);
            
            FileUpload.CommandType = CommandType.StoredProcedure;
            FileUpload.Parameters.Add(new SqlParameter("@handle", SqlDbType.UniqueIdentifier));
            FileUpload.Parameters.Add(new SqlParameter("@timeout", SqlDbType.Int ));
            FileUpload.Parameters.Add(new SqlParameter("@message", SqlDbType.NVarChar, 400000));
            FileUpload.Parameters[0].Value = handle;
            FileUpload.Parameters[1].Value = 60000;
            FileUpload.Parameters[2].Direction = ParameterDirection.Output;
            FileUpload.CommandTimeout = 0;

           

            Stopwatch sw = new Stopwatch();
            sw.Start();
            monCon.Open();
            FileUpload.ExecuteNonQuery();
            monCon.Close();
            
            string message = FileUpload.Parameters[2].Value.ToString ();

            sw.Stop();

            lstFileUploadResults.Invoke (new UpdateList (UpdateListStatus ),new object []{message,sw.ElapsedMilliseconds });

           
        }

        void UpdateListStatus(string message, long time)
                
        {
            lstFileUploadResults.Items.Add(new ListViewItem(new string[] { message.Substring (Math.Max(0,message.Length -40)) , time.ToString() }));
            Application.DoEvents();
        }

        private void btnUpload_Click(object sender, EventArgs e)
        {

            Stopwatch sw = new Stopwatch();
            sw.Start();
            foreach (string file in Directory.GetFiles(txtDirectory.Text))
            {
                FileUpload(file);

            }

            sw.Stop();

            UpdateListStatus (txtDirectory.Text, sw.ElapsedMilliseconds);

        }

        private void btnUploadAsync_Click(object sender, EventArgs e)
        {

            Stopwatch sw = new Stopwatch();
            sw.Start();
            foreach (string file in Directory.GetFiles(txtDirectory.Text))
            {
                FileUploadAsync(file);
            }

            sw.Stop();

            UpdateListStatus (txtDirectory.Text, sw.ElapsedMilliseconds);

        }

        private void btnClearList_Click(object sender, EventArgs e)
        {
            lstFileUploadResults.Items.Clear();
        }

        private void btnSelectFolder_Click(object sender, EventArgs e)
        {
            folderBrowser.SelectedPath = txtDirectory.Text;
            folderBrowser.ShowDialog();
            txtDirectory.Text = folderBrowser.SelectedPath;
 
        }

        private void btnClearTable_Click(object sender, EventArgs e)
        {
            SqlCommand FileUpload = new SqlCommand("Truncate table FileContent", AsyncDB );

            FileUpload.CommandType = CommandType.Text ;
            FileUpload.CommandTimeout = 0;

            Stopwatch sw = new Stopwatch();
            sw.Start();
            AsyncDB.Open();
            FileUpload.ExecuteNonQuery();
            AsyncDB.Close();
            
            
        }
    }
}